package com.tian.service.impl;

import com.tian.entity.ChargeUserCoupon;
import com.tian.entity.MessageUseCouponFailed;
import com.tian.enums.UserCouponStatusEnum;
import com.tian.mapper.ChargeUserCouponMapper;
import com.tian.mapper.MessageUseCouponFailedMapper;
import com.tian.mapper.UserCouponExpireTemporaryMapper;
import com.tian.message.UserCouponMessage;
import com.tian.service.UserUseCouponService;
import com.tian.util.ChargeMarketRedisKeyPrefix;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * {@code @description:} 使用优惠券
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-10-14 22:38
 * {@code @version:} 1.0
 */
@Service
public class UserUseCouponServiceImpl implements UserUseCouponService {
    @Resource
    private ChargeUserCouponMapper chargeUserCouponMapper;
    @Resource
    private MessageUseCouponFailedMapper messageUseCouponFailedMapper;
    @Resource
    private UserCouponExpireTemporaryMapper userCouponExpireTemporaryMapper;
    @Resource
    private RedissonClient redissonClient;

    @Override
    public void changeCouponStatus(UserCouponMessage userCouponMessage) {
        //预支付消息有优惠券id列表
        if (!CollectionUtils.isEmpty(userCouponMessage.getUserCouponIdList())) {
            List<ChargeUserCoupon> chargeUserCoupons = chargeUserCouponMapper.selectByIdList(userCouponMessage.getUserCouponIdList());
            chargeUserCoupons.forEach(chargeUserCoupon -> {
                // 防止并发问题修改状态
                if (chargeUserCoupon.getStatus() == UserCouponStatusEnum.INIT.getStatus()) {
                    RLock lock = redissonClient.getLock("update_user_coupon_status:" + chargeUserCoupon.getId());
                    lock.lock();
                    try {
                        ChargeUserCoupon userCoupon = chargeUserCouponMapper.selectByPrimaryKey(chargeUserCoupon.getId());
                        if (userCoupon.getStatus() == UserCouponStatusEnum.INIT.getStatus()) {
                            chargeUserCouponMapper.using(userCouponMessage.getUserCouponIdList(), userCouponMessage.getOrderId());
                        }
                    } finally {
                        lock.unlock();
                    }
                }
            });

            return;
        }
        Date useTime = userCouponMessage.getStatus() == UserCouponStatusEnum.USED.getStatus() ? new Date() : null;
        List<ChargeUserCoupon> chargeUserCoupons = chargeUserCouponMapper.selectByOrderId(userCouponMessage.getOrderId());
        // 防止预支付消息没有消费，而支付回调通知消息消息先到达
        if (CollectionUtils.isEmpty(chargeUserCoupons)) {
            MessageUseCouponFailed messageUseCouponFailed = new MessageUseCouponFailed();
            messageUseCouponFailed.setOrderId(userCouponMessage.getOrderId());
            messageUseCouponFailed.setStatus(0);
            messageUseCouponFailed.setUseTime(useTime);
            messageUseCouponFailedMapper.insert(messageUseCouponFailed);
            return;
        }
        //不是已使用，直接回滚用户优惠到未使用状态
        if(userCouponMessage.getStatus() != UserCouponStatusEnum.USED.getStatus()){
            redissonClient.getAtomicLong(ChargeMarketRedisKeyPrefix.USER_AVAILABLE_COUPON_COUNT_KEY + userCouponMessage.getUserId()).incrementAndGet();
        }
        userCouponExpireTemporaryMapper.doExpire(userCouponMessage.getOrderId());
        // 支付回调修改优惠券状态
        chargeUserCouponMapper.updateStatus(userCouponMessage.getUserId(), userCouponMessage.getStatus(), userCouponMessage.getOrderId(), useTime);
    }
}
